package cn.xinfei.xdecision.data.core.frame.executors.collect.handler;

import cn.xinfei.xdecision.common.model.datax.consts.VariableConst;
import cn.xinfei.xdecision.common.model.datax.datamanage.v2.Variable;
import cn.xinfei.xdecision.common.model.datax.enums.InputVariableEnum;
import cn.xinfei.xdecision.common.service.datax.datamanage.v2.VariableParamService;
import cn.xinfei.xdecision.common.service.datax.datamanage.v2.VariableService;
import cn.xinfei.xdecision.common.service.rpc.RpcContext;
import cn.xinfei.xdecision.data.core.cache.VarParamsCache;
import cn.xinfei.xdecision.data.core.frame.executors.collect.VarHandler;
import cn.xinfei.xdecision.data.core.frame.executors.collect.VariableHelper;
import cn.xinfei.xdecision.data.core.frame.executors.VarContext;
import cn.xinfei.xdecision.data.core.vo.VarCollectAwareVO;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.InvalidParameterException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class VarInputParamVerifyHandler implements VarHandler<VarCollectAwareVO> {

    @Autowired
    VariableParamService variableParamService;
    @Autowired
    VariableService variableService;
    @Autowired
    VarParamsCache varParamsCache;

    @Override
    public void doHandle(VarContext<VarCollectAwareVO> context) {
        VarCollectAwareVO varCollectAwareVO = context.get();
        Set<String> varCodes = varCollectAwareVO.getVarCodes();
        JSONObject varInputContext = varCollectAwareVO.getInputPrarams();
        vaildateVarParams(varCollectAwareVO.getRequestId(), varInputContext, varCodes);
    }

    private void vaildateVarParams(String requestId, JSONObject context, Set<String> varCodes) {

        Optional<Map<String, Set<String>>> varAndParamsCache = Optional.ofNullable(varParamsCache.loadVarParams());
        Map<String, Set<String>> varAndParamsMap = Maps.newHashMap();
        if (varAndParamsCache.isPresent()) {
            varAndParamsMap = varAndParamsCache.get()
                    .entrySet()
                    .stream()
                    .filter(entry -> varCodes.contains(entry.getKey()))
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
            log.info("requestId = {} 查询 VarAndParamsCache 缓存, varAndParams = {}", requestId, JSONObject.toJSONString(varAndParamsMap));
        } else {
            log.error("requestId = {} 查询 VarAndParamsCache 缓存失败!", requestId);
        }
        if (MapUtils.isNotEmpty(varAndParamsMap)) {
            for (Map.Entry<String, Set<String>> entry : varAndParamsMap.entrySet()) {
                String varCode = entry.getKey();
                Set<String> varParamCodes = entry.getValue();
                for (String varParamCode : varParamCodes) {
                    if (!context.containsKey(varParamCode)) {
                        log.info("varCode = {} 必传参数: [{}] 缺失！请重新配置该变量的参数依赖!", varCode, varParamCode);
                    }
                }
            }
        }
    }


    public String get(JSONObject context, InputVariableEnum inputVariable) {
        if (context.containsKey(inputVariable.getCode())) {
            return context.getString(inputVariable.getCode());
        } else if (null != RpcContext.getCurrentAttribute(inputVariable.getCode())) {
            return RpcContext.getCurrentString(inputVariable.getCode());
        }
        return null;
    }

    public Object get(JSONObject context, String inputVariable) {
        if (context.containsKey(inputVariable)) {
            return context.get(inputVariable);
        } else if (null != RpcContext.getCurrentAttribute(inputVariable)) {
            return RpcContext.getCurrentString(inputVariable);
        }
        return null;
    }

    public <T> T getSingleDefaultValue(List<String> varCodes) {
        List<Variable> variableByIds = variableService.findVariables(varCodes);
        if (null == variableByIds || variableByIds.size() <= 0) {
            throw new InvalidParameterException(VariableConst.DATA_TRANSFER_FATAL_PREFIX + "variables :" + varCodes + " 获取不到默认值!");
        }
        return (T) VariableHelper.getDefaultValue(variableByIds.get(0));
    }

}
